#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

#define PAGEMAP_ENTRY_SIZE 8
#define PAGE_SHIFT 12

int main() {
    int pagemap_fd;
    uintptr_t virt_addr;
    uint64_t pagemap_entry;
    uintptr_t phys_addr;
    int pid;
    char pagemap_file[64];

    // 分配内存并初始化一个整数值
    int *value = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    *value = 42;

    // 获取当前进程ID和pagemap文件路径
    pid = getpid();
    snprintf(pagemap_file, sizeof(pagemap_file), "/proc/%d/pagemap", pid);

    // 打开pagemap文件
    pagemap_fd = open(pagemap_file, O_RDONLY);
    if (pagemap_fd == -1) {
        perror("Failed to open pagemap file");
        return 1;
    }

    // 计算pagemap中的偏移量
    off_t offset = ((uintptr_t)value / getpagesize()) * PAGEMAP_ENTRY_SIZE;

    // 读取pagemap条目
    if (pread(pagemap_fd, &pagemap_entry, PAGEMAP_ENTRY_SIZE, offset) != PAGEMAP_ENTRY_SIZE) {
        perror("Failed to read pagemap entry");
        close(pagemap_fd);
        return 1;
    }

    // 计算物理地址
    phys_addr = (pagemap_entry & ((1ULL << 54) - 1)) << PAGE_SHIFT;
    phys_addr |= (uintptr_t)value & ((1 << PAGE_SHIFT) - 1);

    printf("Virtual address: 0x%lx, Physical address: 0x%lx, Value: %d\n", (uintptr_t)value, phys_addr, *value);

    // 清理
    munmap(value, sizeof(int));
    close(pagemap_fd);

    return 0;
}
